package com.itheima.concurrent;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;

/**
 * CountDownLatch 是一个同步工具类，用来协调多个线程之间的同步，或者说起到线程之间的通信（而不是用作互斥的作用）。
 * CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后，再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。
 * 当每一个线程完成自己任务后，计数器的值就会减一。当计数器的值为0时，表示所有的线程都已经完成一些任务，然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。
 * CountDownLatch是一次性的，计算器的值只能在构造方法中初始化一次，之后没有任何机制再次对其设置值，当CountDownLatch使用完毕后，它不能再次被使用
 */
public class CountDownLatchTest {

    // 用于聚合所有的统计指标, 因为是多线程环境所以不要map
    private static ConcurrentHashMap<String,Object> resultMap = new ConcurrentHashMap<>();

    // 创建计数器，这里需要统计4个指标 用户新增数量、订单数量、商品的总销量、总销售额；
    private static CountDownLatch countDownLatch = new CountDownLatch(4);

    public static void main(String[] args) throws Exception {
        // 记录开始时间
        long startTime=System.currentTimeMillis();

        /** 1.模拟统计新增用户数量 */
        Thread userThread = new Thread(() -> {
            System.out.println("正在统计新增用户数量");
            try {
                Thread.sleep(3000); // 任务执行需要3秒
                resultMap.put("userCount", 35); // 保存结果
                countDownLatch.countDown(); // 标记已经完成一个任务
                System.out.println("统计新增用户数量完毕");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        /** 2.模拟统计订单数量 */
        Thread orderThread = new Thread(() -> {
            System.out.println("正在统计订单数量");
            try {
                Thread.sleep(3000); // 任务执行需要3秒
                resultMap.put("orderCount", 142); // 保存结果
                countDownLatch.countDown(); // 标记已经完成一个任务
                System.out.println("统计订单数量完毕");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });


        /** 3.模拟商品的总销量 */
        Thread goodsThread = new Thread(() -> {
            System.out.println("正在统计商品的总销量");
            try {
                Thread.sleep(3000); // 任务执行需要3秒
                resultMap.put("productCount", 1257); // 保存结果
                countDownLatch.countDown(); // 标记已经完成一个任务
                System.out.println("统计商品的总销量完毕" );
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        /** 4.模拟商品的总销售额 */
        Thread moneyThread = new Thread(() -> {
            System.out.println("正在统计商品的总销售额");
            try {
                Thread.sleep(3000); // 任务执行需要3秒
                resultMap.put("moneyCount", 24587); // 保存结果
                countDownLatch.countDown(); // 标记已经完成一个任务
                System.out.println("统计商品的总销售额完毕" );
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        // 新怎自己的分支
        //启动子线程执行任务
        userThread.start();
        orderThread.start();
        goodsThread.start();
        moneyThread.start();


        // 主线程等待所有统计指标执行完毕
        countDownLatch.await();
        // 记录结束时间
        long endTime=System.currentTimeMillis();
        System.err.println("统计结果为：" + resultMap.toString());
        System.out.println("任务总执行时间为"+(endTime-startTime)/1000+"秒");
    }
}
